﻿/**

 * Copyright (c) 2015-2016, FastDev 刘强 (fastdev@163.com) & Quincy.

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

using MsgPack.Serialization;
using OF.Cache2.Entity;
using StackExchange.Redis;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OF.Cache2.Core;
using OF.Cache2.Entity;

namespace OF.Cache2.Redis
{
    public class RedisBusinessHelper
    {
        private byte[] hostIdArray;
        private int dbIndex;
        private string businessCode = null;
        private int expireSeconds = 0;
        private IOnRedisMessageChange iOnMessageChange = null;
        private ISubscriber iSubscriber = null;

        private string removeEventChannel = null;
        public RedisBusinessHelper(byte hostId, int dbIndex, string businessCode,
            IOnRedisMessageChange iOnMessageChange = null, int expireSeconds = 0)
        {
            this.hostIdArray = new byte[] { hostId };
            this.dbIndex = dbIndex;
            this.businessCode = businessCode;
            this.iOnMessageChange = iOnMessageChange;
            this.expireSeconds = expireSeconds;
            this.iSubscriber = RedisHelper.Manager.GetSubscriber();
            string sDBIndex = dbIndex.ToString();
            this.removeEventChannel = RedisHelper.MergeKey("RedisBusinessHelper", "OnMessageRemoved", sDBIndex, businessCode);
            if (iOnMessageChange != null)
            {
                this.iSubscriber.Subscribe(removeEventChannel, iOnMessageChange.OnMessageRemoved);
            }
        }

        public bool Remove(string dataKey)
        {
            string buKey = RedisHelper.MergeKey(businessCode, dataKey);
            var db = RedisHelper.Manager.GetDatabase(dbIndex);
            bool result = db.KeyDelete(buKey);
            TryPublishRemoved(dataKey);
            return result;
        }

        public RedisValue GetValue(string key)
        {
            key = RedisHelper.MergeKey(businessCode, key);
            var db = RedisHelper.Manager.GetDatabase(dbIndex);
            return db.StringGet(key);
        }

        public byte[] GetBytes(string key)
        {
            return GetValue(key);
        }

        public string GetString(string key)
        {
            return GetValue(key);
        }

        public bool SetBytes(string dataKey, byte[] value)
        {
            string buKey = RedisHelper.MergeKey(businessCode, dataKey);
            var db = RedisHelper.Manager.GetDatabase(dbIndex);
            bool result = false;
            if (expireSeconds > 0)
            {
                result = db.StringSet(buKey, value, TimeSpan.FromSeconds(expireSeconds));
            }
            else
            {
                result = db.StringSet(buKey, value);
            }
            TryPublishRemoved(dataKey);
            return result;
        }

        private void TryPublishRemoved(string dataKey)
        {
            try
            {
                byte[] publishData = RedisHelper.CombineKeyData(dataKey, hostIdArray);
                iSubscriber.Publish(removeEventChannel, publishData);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public bool HasKey(string key)
        {
            key = RedisHelper.MergeKey(businessCode, key);
            var db = RedisHelper.Manager.GetDatabase(dbIndex);
            return db.KeyExists(key);
        }
    }
}
